using System.Linq;
using FireStarter.Base;
using FireStarter.Base.BusinessObjectMerger;
using FireStarterModeller.BO;
using FireStarterModeller.Logic.MergeBusinessObjects;
using FireStarterModeller.Test.BO;
using Habanero.Testability;
using NUnit.Framework;

namespace FireStarterModeller.Test.Logic.MergeBusinessObjects
{
    [TestFixture]
    public class TestMergeUIGridFilter
    {
        [TestFixtureSetUp]
        public virtual void TestFixtureSetup()
        {
            TestUtilsLogic.SetupFixture();
        }
        [SetUp]
        public virtual void SetupTest()
        {
            TestUtilsLogic.SetupTest();
        }

        [Test]
        public void Test_MergeUIGridFilter_WhenNoExistingUIGridFilterProps_ShouldMergeUIGridFilterProps()
        {
            //---------------Set up test pack-------------------
            var uiGridFilterPropMerger = MergeableBORegistry.Instance.Resolve<UIGridFilter>();
            var fromUIGridFilter = TestUtilsUIGridFilter.GetFactory()
                .WithMany(columnLayout => columnLayout.UIGridFilterProps)
                .WithOutSingleRelationships()
                .CreateValidBusinessObject();
            var uiGridFilterProps = fromUIGridFilter.UIGridFilterProps;
            SetOrdinalPos(uiGridFilterProps[0]);
            SetOrdinalPos(uiGridFilterProps[1]);
            SetOrdinalPos(uiGridFilterProps[2]);
            var toUIGridFilter = new UIGridFilter();
            //---------------Assert Precondition----------------
            Assert.Greater(fromUIGridFilter.UIGridFilterProps.Count, 2);
            Assert.AreEqual(0, toUIGridFilter.UIGridFilterProps.Count);
            //---------------Execute Test ----------------------
            uiGridFilterPropMerger.MergeBOFrom(fromUIGridFilter, toUIGridFilter);
            //---------------Test Result -----------------------
            Assert.AreEqual(fromUIGridFilter.UIGridFilterProps.Count, toUIGridFilter.UIGridFilterProps.Count);
        }

        [Test]
        public void Test_MergeUIGridFilter_WhenTwoUpdatedFilterProps_ShouldUpdateFilterProps()
        {
            //---------------Set up test pack-------------------
            var uiGridFilterPropMerger = MergeableBORegistry.Instance.Resolve<UIGridFilter>();
            var fromUIGridFilter = TestUtilsUIGridFilter.GetFactory()
                .WithTwo(columnLayout => columnLayout.UIGridFilterProps)
                .WithOutSingleRelationships()
                .CreateValidBusinessObject();
            var uiGridFilterProps = fromUIGridFilter.UIGridFilterProps;
            var fromUIGridFilterProp = uiGridFilterProps[0];
            SetOrdinalPos(fromUIGridFilterProp);
            var fromUIGridFilterProp2 = uiGridFilterProps[1];
            SetOrdinalPos(fromUIGridFilterProp2);

            var toUIGridFilter = new UIGridFilter ();
            UIGridFilterProp expectedToUIGridFilterProp = AddCopiedUIGridFilterProp(toUIGridFilter, fromUIGridFilterProp);
            UIGridFilterProp expectedToUIGridFilterProp2 = AddCopiedUIGridFilterProp(toUIGridFilter, fromUIGridFilterProp2);

            //---------------Assert Precondition----------------
            Assert.AreEqual(2, fromUIGridFilter.UIGridFilterProps.Count);
            Assert.AreEqual(fromUIGridFilterProp.PropertyName, expectedToUIGridFilterProp.PropertyName);
            //MergeUIGridFilterProp Specialises the matchBusinessObject            Assert.AreEqual(fromUIGridFilterProp.ToString(), expectedToUIGridFilterProp.ToString());
            Assert.AreNotEqual(fromUIGridFilterProp.OrdinalPosition, expectedToUIGridFilterProp.OrdinalPosition);
            Assert.AreEqual(fromUIGridFilterProp2.PropertyName, expectedToUIGridFilterProp2.PropertyName);
            Assert.AreNotEqual(fromUIGridFilterProp2.OrdinalPosition, expectedToUIGridFilterProp2.OrdinalPosition);
            //MergeUIGridFilterProp Specialises the matchBusinessObject         Assert.AreEqual(fromUIGridFilterProp2.ToString(), expectedToUIGridFilterProp2.ToString());
            //---------------Execute Test ----------------------
            uiGridFilterPropMerger.MergeBOFrom(fromUIGridFilter, toUIGridFilter);
            //---------------Test Result -----------------------
            Assert.IsNotNull(toUIGridFilter);
            Assert.AreEqual(2, toUIGridFilter.UIGridFilterProps.Count);
            var toUIGridFilterProp = toUIGridFilter.UIGridFilterProps.First();
            Assert.AreEqual(fromUIGridFilterProp.PropertyName, toUIGridFilterProp.PropertyName);
            Assert.AreEqual(fromUIGridFilterProp.OrdinalPosition, toUIGridFilterProp.OrdinalPosition);
            var toUIGridFilterProp2 = toUIGridFilter.UIGridFilterProps.Last();
            Assert.AreEqual(fromUIGridFilterProp2.PropertyName, toUIGridFilterProp2.PropertyName);
            Assert.AreEqual(fromUIGridFilterProp2.OrdinalPosition, toUIGridFilterProp2.OrdinalPosition);
        }

        private static void SetOrdinalPos(UIGridFilterProp uiGridFilterProp)
        {
            uiGridFilterProp.OrdinalPosition = GetValidOrdinalPos(uiGridFilterProp);
        }

        private static int? GetValidOrdinalPos(UIGridFilterProp uiGridFilterProp)
        {
            return GetFactory().GetValidPropValue(uiGridFilterProp, layout => layout.OrdinalPosition);
        }

        private static BOTestFactory<UIGridFilterProp> GetFactory()
        {
            return TestUtilsUIGridFilterProp.GetFactory();
        }
        [Test]
        public void Test_MergeUIGridFilter_WhenOneRemovedUIGridFilter_ShouldUpdateFieldStatusToDelete()
        {
            //---------------Set up test pack-------------------
            var uiGridFilterPropMerger = MergeableBORegistry.Instance.Resolve<UIGridFilter>();
            var fromUIGridFilter = new UIGridFilter();
            var fromUIGridFilterProp = CreateUIGridFilterProp(fromUIGridFilter);
            var fromUIGridFilterProp2 = CreateUIGridFilterProp(fromUIGridFilter);
            var toUIGridFilter = new UIGridFilter();
            UIGridFilterProp expectedToUIGridFilterProp = AddCopiedUIGridFilterProp(toUIGridFilter, fromUIGridFilterProp);
            UIGridFilterProp expectedToUIGridFilterProp2 = AddCopiedUIGridFilterProp(toUIGridFilter, fromUIGridFilterProp2);
            fromUIGridFilter.UIGridFilterProps.Remove(fromUIGridFilterProp2);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, fromUIGridFilter.UIGridFilterProps.Count);
            Assert.AreEqual(2, toUIGridFilter.UIGridFilterProps.Count);
            Assert.AreNotEqual(fromUIGridFilterProp.OrdinalPosition, expectedToUIGridFilterProp.OrdinalPosition);
            Assert.AreNotEqual(ChangeType.Update, ((IMergableBo) expectedToUIGridFilterProp).PendingChangeType);
            Assert.AreNotEqual(ChangeType.Delete, ((IMergableBo)expectedToUIGridFilterProp2).PendingChangeType);
            //---------------Execute Test ----------------------
            uiGridFilterPropMerger.MergeBOFrom(fromUIGridFilter, toUIGridFilter);
            //---------------Test Result -----------------------

            Assert.IsNotNull(toUIGridFilter);
            Assert.AreEqual(2, toUIGridFilter.UIGridFilterProps.Count);
            var toUIGridFilterProp = toUIGridFilter.UIGridFilterProps.First();
            Assert.AreSame(toUIGridFilterProp, expectedToUIGridFilterProp);

            var toUIGridFilterProp2 = toUIGridFilter.UIGridFilterProps.Last();
            Assert.AreSame(toUIGridFilterProp2, expectedToUIGridFilterProp2);
            Assert.AreEqual(ChangeType.Delete, ((IMergableBo)toUIGridFilterProp2).PendingChangeType);
            Assert.AreEqual(ChangeType.None, ((IMergableBo)toUIGridFilterProp).PendingChangeType);
        }
        [Test]
        public void Test_MergeUIGridFilter_WhenMergeToNotNull_ShouldUpdateUIGridFilter()
        {
            //---------------Set up test pack-------------------
            IMergeBO<UIGridFilter> mergeBO = MergeableBORegistry.Instance.Resolve<UIGridFilter>();
            var boTestFactory = TestUtilsUIGridFilter.GetFactory();
            var fromUIGridFilter = boTestFactory
                .WithOutSingleRelationships()
                .CreateValidBusinessObject();
            fromUIGridFilter.Columns = boTestFactory.GetValidPropValue(filter => filter.Columns);
            var toUIGridFilter = new UIGridFilter();
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(fromUIGridFilter.Columns, toUIGridFilter.Columns);
            //---------------Execute Test ----------------------
            mergeBO.MergeBOFrom(fromUIGridFilter, toUIGridFilter);
            //---------------Test Result -----------------------
            Assert.AreEqual(fromUIGridFilter.Columns, toUIGridFilter.Columns);
        }
        private static UIGridFilterProp AddCopiedUIGridFilterProp(UIGridFilter toUIGridFilter, UIGridFilterProp fromUIGridFilterProp)
        {
            var expectedToUIGridFilterProp = new UIGridFilterProp { PropertyName = fromUIGridFilterProp.PropertyName };
            expectedToUIGridFilterProp.OrdinalPosition = GetFactory().GetValidPropValue(gridFilterProp => gridFilterProp.OrdinalPosition);
            toUIGridFilter.UIGridFilterProps.Add(expectedToUIGridFilterProp);
            return expectedToUIGridFilterProp;
        }

        private static UIGridFilterProp CreateUIGridFilterProp(UIGridFilter uiGridFilter)
        {
            var uiGridFilterProp = uiGridFilter.UIGridFilterProps.CreateBusinessObject();
            uiGridFilterProp.OrdinalPosition = GetFactory().GetValidPropValue(gridFilterProp => gridFilterProp.OrdinalPosition);
            uiGridFilterProp.PropertyName = GetFactory().GetValidPropValue(gridFilterProp => gridFilterProp.PropertyName);
            return uiGridFilterProp;
        }


        [Test]
        public void Test_MatchUIGridFilterProp_WhenPropNameSame_ShouldRetTrue()
        {
            //---------------Set up test pack-------------------
            MergeBO<UIGridFilterProp> mergeBO = new MergeUIGridFilterProp();
            var filterProp = new UIGridFilterProp
            {
                PropertyName = TestUtilsShared.GetRandomString()
            };
            var filterProp2 = new UIGridFilterProp
            {
                PropertyName = filterProp.PropertyName
            };
            //---------------Assert Precondition----------------
            Assert.AreEqual(filterProp.PropertyName, filterProp2.PropertyName);
            //---------------Execute Test ----------------------
            bool matchBO = mergeBO.MatchBusinessObject(filterProp).Invoke(filterProp2);
            //---------------Test Result -----------------------
            Assert.IsTrue(matchBO);
        }

        [Test]
        public void Test_MatchUIGridFilterProp_WhenPropNameDiff_ShouldRetFalse()
        {
            //---------------Set up test pack-------------------
            MergeBO<UIGridFilterProp> mergeBO = new MergeUIGridFilterProp();
            var filterProp = new UIGridFilterProp
            {
                PropertyName = TestUtilsShared.GetRandomString()
            };
            var filterProp2 = new UIGridFilterProp
            {
                PropertyName = TestUtilsShared.GetRandomString()
            };
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(filterProp.PropertyName, filterProp2.PropertyName);
            //---------------Execute Test ----------------------
            bool matchBO = mergeBO.MatchBusinessObject(filterProp).Invoke(filterProp2);
            //---------------Test Result -----------------------
            Assert.IsFalse(matchBO);
        }
    }
}